#include "Define.h"
#include "S32K146.h"
#include "main.h"

#define LOOPBACK    0
#define DMA_ENABLE         1


uint32_t can0_rxBuffer[4] __attribute__ ((aligned (32)));
uint32_t can1_rxBuffer[4] __attribute__ ((aligned (32)));
uint32_t can2_rxBuffer[4] __attribute__ ((aligned (32)));

CAN_FrameStruct  canTxMsg, canRxMsg;
CAN_FrameStruct  can1TxMsg, can1RxMsg;
CAN_FrameStruct  can2TxMsg, can2RxMsg;

uint32_t rxCounter = 0;
uint32_t dmarxCounter = 0;
uint32_t txCounter = 0;
uint32_t txBusy = 0;
uint32_t can1_rxCounter = 0;
uint32_t can1_dmarxCounter = 0;
uint32_t can1_txCounter = 0;
uint32_t can1_txBusy = 0;
uint32_t can2_rxCounter = 0;
uint32_t can2_dmarxCounter = 0;
uint32_t can2_txCounter = 0;
uint32_t can2_txBusy = 0;

#define CAN_WMBn_CS_CODE_MASK                    0x0F000000u
#define CAN_WMBn_CS_CODE_SHIFT                   24u
#define CAN_WMBn_CS_CODE_WIDTH                   4u
#define CAN_WMBn_CS_CODE(x)                      (((uint32_t)(((uint32_t)(x))<<CAN_WMBn_CS_CODE_SHIFT))&CAN_WMBn_CS_CODE_MASK)


const CAN_Cfg cancfg[3]={
    {0,CAN0_MBS_MAX,CAN0_MBS_MAX*4,MB_FIFO_NUM,{CAN0_DMA_CH,DMA12_IRQn,0x0A,54,&CAN0->RAMn[0],&can0_rxBuffer[0]}},
    {1,CAN1_MBS_MAX,CAN1_MBS_MAX*4,MB_FIFO_NUM,{CAN1_DMA_CH,DMA13_IRQn,0x0A,55,&CAN1->RAMn[0],&can1_rxBuffer[0]}},
    {2,CAN2_MBS_MAX,CAN2_MBS_MAX*4,MB_FIFO_NUM,{CAN2_DMA_CH,DMA14_IRQn,0x0A,56,&CAN2->RAMn[0],&can2_rxBuffer[0]}},
};

/**
 * CAN Port Initialization
 */
void FLEXCAN0_Port_Init(void)
{
    // Enable clock to PORTE
    if(PCC->PCCn[PCC_PORTE_INDEX] & PCC_PCCn_PR_MASK)
    {
        PCC->PCCn[PCC_PORTE_INDEX] |= PCC_PCCn_CGC(1); // Clock enabled to PORTE
    }

#if LOOPBACK == 0
    // Set MUX
    // PTE4 - CAN0_RX
    // Port E4: MUX = ALT5, CAN0_RX
    PORTE->PCR[CAN0_PORT_RX_IDX] = PORT_PCR_MUX(5);
    // PTE5 - CAN0_TX
    // Port E5: MUX = ALT5, CAN0_TX
    PORTE->PCR[CAN0_PORT_TX_IDX] = PORT_PCR_MUX(5);
#endif    
}

void FLEXCAN1_Port_Init(void)
{
    // Enable clock to PORTE
    if(PCC->PCCn[PCC_PORTC_INDEX] & PCC_PCCn_PR_MASK)
    {
        PCC->PCCn[PCC_PORTC_INDEX] |= PCC_PCCn_CGC(1); // Clock enabled to PORTE
    }

#if LOOPBACK == 0
    // Set MUX
    // PTC6 - CAN0_RX
    // Port E6: MUX = ALT3, CAN1_RX
    PORTC->PCR[CAN1_PORT_RX_IDX] = PORT_PCR_MUX(3);
    // PTC7 - CAN0_TX
    // Port C7: MUX = ALT3, CAN1_TX
    PORTC->PCR[CAN1_PORT_TX_IDX] = PORT_PCR_MUX(3);
#endif    
}

void FLEXCAN2_Port_Init(void)
{
    // Enable clock to PORTE
    if(PCC->PCCn[PCC_PORTB_INDEX] & PCC_PCCn_PR_MASK)
    {
        PCC->PCCn[PCC_PORTB_INDEX] |= PCC_PCCn_CGC(1); // Clock enabled to PORTE
    }

#if LOOPBACK == 0
    // Set MUX
    // PTB12 - CAN2_RX
    // Port B12: MUX = ALT5, CAN2_RX
    PORTB->PCR[CAN2_PORT_RX_IDX] = PORT_PCR_MUX(4);
    // PTB13 - CAN2_TX
    // Port B13: MUX = ALT5, CAN2_TX
    PORTB->PCR[CAN2_PORT_TX_IDX] = PORT_PCR_MUX(4);
#endif    
}




/*******************************************************************************
Function Name : DMA_init
Engineer      : Petr Stancik
Date          : Sep-4-2017
Parameters    : NONE
Modifies      : NONE
Returns       : NONE
Notes         : Transfer Control Descriptor 0 : HW start --> FlexCAN0 RXFIFO to Memory
Issues        : NONE
*******************************************************************************/
void CAN_DMA_init(const CAN_Dma_Cfg *dma)
{
  uint8_t DMA_CHn = dma->DMA_Ch;

  PCC->PCCn[PCC_DMAMUX_INDEX] |= PCC_PCCn_CGC_MASK;          	// CGC=1: Clock enabled for DMA0

  DMA->TCD[DMA_CHn].CSR &= 0xFFFFFFFF ^ DMA_TCD_CSR_DONE_MASK;  					// Clear Channel Done flag
  DMA->TCD[DMA_CHn].SADDR = DMA_TCD_SADDR_SADDR(dma->SrcAddr);  				// Source Address
  DMA->TCD[DMA_CHn].SOFF = DMA_TCD_SOFF_SOFF(4);                					// Source Offset
  DMA->TCD[DMA_CHn].ATTR = DMA_TCD_ATTR_SMOD(0)  |              					// Source address modulo feature is disabled
                    DMA_TCD_ATTR_SSIZE(2) |              					// Source data transfer size: 1: 16-bit, 2=32-bit
                    DMA_TCD_ATTR_DMOD(0)  |              					// Destination address modulo feature: 0=disabled, x= x power of 2 buffer[DMOD=4->buffer of 16bytes]
                    DMA_TCD_ATTR_DSIZE(2);               					// Destination data transfer size: 1: 16-bit, 2=32-bit
  DMA->TCD[DMA_CHn].NBYTES.MLOFFNO = DMA_TCD_NBYTES_MLNO_NBYTES(16); 				// Minor Byte Transfer Count is 4-bytes
  DMA->TCD[DMA_CHn].SLAST = DMA_TCD_SLAST_SLAST(-16);             					// Last Source Address Adjustment is -16
  DMA->TCD[DMA_CHn].DADDR = DMA_TCD_DADDR_DADDR(dma->DstAddr);     			// Destination Address of Buffer
  DMA->TCD[DMA_CHn].DOFF = DMA_TCD_DOFF_DOFF(4);                					// Destination Address Signed Offset is 4
  DMA->TCD[DMA_CHn].CITER.ELINKNO = DMA_TCD_CITER_ELINKNO_CITER(1)  				// Current Major Iteration Count is 4
                                     | DMA_TCD_CITER_ELINKNO_ELINK(0);  	// The channel-to-channel linking is disabled
  DMA->TCD[DMA_CHn].DLASTSGA = DMA_TCD_DLASTSGA_DLASTSGA(-16);    					// Destination last address adjustment is -16
  DMA->TCD[DMA_CHn].BITER.ELINKNO = DMA_TCD_BITER_ELINKNO_BITER(1) | 				// Starting major iteration count is 4
                                       DMA_TCD_BITER_ELINKNO_ELINK(0);  	// The minor channel-to-channel linking is disabled
  DMA->TCD[DMA_CHn].CSR = DMA_TCD_CSR_BWC(0)         |         					// BWC=0: No eDMA engine stalls - full bandwidth
                    DMA_TCD_CSR_MAJORELINK(0)  |        					// The channel-to-channel linking is disabled
                    DMA_TCD_CSR_MAJORLINKCH(0) |       						// channel 1 will be called from ch0
                    DMA_TCD_CSR_ESG(0)         |         					// The current channel�fs TCD is normal format - No scatter/gather
                    DMA_TCD_CSR_DREQ(0)        |         					// The channel's ERQ bit is not affected
                    DMA_TCD_CSR_INTHALF(0)     |         					// The half-point interrupt is disabled
                    DMA_TCD_CSR_INTMAJOR(1)    |         					// The end-of-major loop interrupt is enabled
                    DMA_TCD_CSR_START(0);                					// The channel is not explicitly started

  DMA->SERQ = DMA_CHn;	// enable DMA channel 12 HW trigger
}

void FLEXCAN_DMAMUX_Init (const CAN_Dma_Cfg *cfg)
{
    DMAMUX->CHCFG[cfg->DMA_Ch] &= ~ DMAMUX_CHCFG_ENBL(1);         // Disabling the DMA channel
    DMAMUX->CHCFG[cfg->DMA_Ch] |= DMAMUX_CHCFG_SOURCE(cfg->IRQs);        // FlexCAN0 is the source of the DMA0 channel
    DMAMUX->CHCFG[cfg->DMA_Ch] |= DMAMUX_CHCFG_ENBL(1);           // Enabling the DMA channel
}

void FLEXCAN_DMA_NVIC_init_IRQs (const CAN_Dma_Cfg *cfg)
{
	S32_NVIC->ICPR[0] = 1 << (cfg->IRQn % 32);  /* IRQ12-DMA ch12: clr any pending IRQ*/
	S32_NVIC->ISER[0] = 1 << (cfg->IRQn % 32);  /* IRQ12-DMA ch12: enable IRQ */
 	S32_NVIC->IP[cfg->IRQn] = 0xA;              /* IRQ12-DMA ch12: priority 10 of 0-15*/
}

//flexcan0
void DMA12_IRQHandler(void)
{
    CAN_FrameStruct *RxMsg=&canRxMsg;

    dmarxCounter++;

	DMA->CINT = 12; // clear DMA channel 0 interrupt flag

    // 1. Read the Control and Status word
    RxMsg->Ide = (can0_rxBuffer[0] & CAN_WMBn_CS_IDE_MASK) >> CAN_WMBn_CS_IDE_SHIFT;
    RxMsg->Rtr = (can0_rxBuffer[0] & CAN_WMBn_CS_RTR_MASK) >> CAN_WMBn_CS_RTR_SHIFT;
    RxMsg->Len = (can0_rxBuffer[0] & CAN_WMBn_CS_DLC_MASK) >> CAN_WMBn_CS_DLC_SHIFT;
    RxMsg->Srr = (can0_rxBuffer[0] & CAN_WMBn_CS_SRR_MASK) >> CAN_WMBn_CS_SRR_SHIFT;
    RxMsg->timestamp = (can0_rxBuffer[0] & 0x000FFFF);
    
    // 2. Read the ID field
    if(!RxMsg->Ide)
    {
        RxMsg->Id = (can0_rxBuffer[1] >> 18) & 0x7FF;      // std id
    }
    else
    {
        RxMsg->Id = (can0_rxBuffer[1] & 0x1FFFFFFF);       // Ext id
    }        
    
    // 3. Read the data field.
    if(!RxMsg->Rtr)
    {                      
        RxMsg->Data[0] = (can0_rxBuffer[2] >> 24) & 0xFF;
        RxMsg->Data[1] = (can0_rxBuffer[2] >> 16) & 0xFF;
        RxMsg->Data[2] = (can0_rxBuffer[2] >> 8) & 0xFF;
        RxMsg->Data[3] = (can0_rxBuffer[2]) & 0xFF;
        RxMsg->Data[4] = (can0_rxBuffer[3] >> 24) & 0xFF;
        RxMsg->Data[5] = (can0_rxBuffer[3] >> 16) & 0xFF;
        RxMsg->Data[6] = (can0_rxBuffer[3] >> 8) & 0xFF;
        RxMsg->Data[7] = (can0_rxBuffer[3]) & 0xFF;
    }
    else               //  Ext id  no data
    {
        for(int i=0; i<8; i++)
        {
            RxMsg->Data[i] = 0;
        }
    }
}

//flexcan1
void DMA13_IRQHandler(void)
{
    CAN_FrameStruct *RxMsg=&can1RxMsg;

    can1_dmarxCounter++;

    DMA->CINT = 13; // clear DMA channel 0 interrupt flag

    // 1. Read the Control and Status word
    RxMsg->Ide = (can1_rxBuffer[0] & CAN_WMBn_CS_IDE_MASK) >> CAN_WMBn_CS_IDE_SHIFT;
    RxMsg->Rtr = (can1_rxBuffer[0] & CAN_WMBn_CS_RTR_MASK) >> CAN_WMBn_CS_RTR_SHIFT;
    RxMsg->Len = (can1_rxBuffer[0] & CAN_WMBn_CS_DLC_MASK) >> CAN_WMBn_CS_DLC_SHIFT;
    RxMsg->Srr = (can1_rxBuffer[0] & CAN_WMBn_CS_SRR_MASK) >> CAN_WMBn_CS_SRR_SHIFT;
    RxMsg->timestamp = (can1_rxBuffer[0] & 0x000FFFF);
    
    // 2. Read the ID field
    if(!RxMsg->Ide)
    {
        RxMsg->Id = (can1_rxBuffer[1] >> 18) & 0x7FF;      // std id
    }
    else
    {
        RxMsg->Id = (can1_rxBuffer[1] & 0x1FFFFFFF);       // Ext id
    }        
    
    // 3. Read the data field.
    if(!RxMsg->Rtr)
    {                      
        RxMsg->Data[0] = (can1_rxBuffer[2] >> 24) & 0xFF;
        RxMsg->Data[1] = (can1_rxBuffer[2] >> 16) & 0xFF;
        RxMsg->Data[2] = (can1_rxBuffer[2] >> 8) & 0xFF;
        RxMsg->Data[3] = (can1_rxBuffer[2]) & 0xFF;
        RxMsg->Data[4] = (can1_rxBuffer[3] >> 24) & 0xFF;
        RxMsg->Data[5] = (can1_rxBuffer[3] >> 16) & 0xFF;
        RxMsg->Data[6] = (can1_rxBuffer[3] >> 8) & 0xFF;
        RxMsg->Data[7] = (can1_rxBuffer[3]) & 0xFF;
    }
    else               //  Ext id  no data
    {
        for(int i=0; i<8; i++)
        {
            RxMsg->Data[i] = 0;
        }
    }
}

//flexcan2
void DMA14_IRQHandler(void)
{
    CAN_FrameStruct *RxMsg=&can2RxMsg;

    can2_dmarxCounter++;

	DMA->CINT = 14; // clear DMA channel 14 interrupt flag

    // 1. Read the Control and Status word
    RxMsg->Ide = (can2_rxBuffer[0] & CAN_WMBn_CS_IDE_MASK) >> CAN_WMBn_CS_IDE_SHIFT;
    RxMsg->Rtr = (can2_rxBuffer[0] & CAN_WMBn_CS_RTR_MASK) >> CAN_WMBn_CS_RTR_SHIFT;
    RxMsg->Len = (can2_rxBuffer[0] & CAN_WMBn_CS_DLC_MASK) >> CAN_WMBn_CS_DLC_SHIFT;
    RxMsg->Srr = (can2_rxBuffer[0] & CAN_WMBn_CS_SRR_MASK) >> CAN_WMBn_CS_SRR_SHIFT;
    RxMsg->timestamp = (can2_rxBuffer[0] & 0x000FFFF);
    
    // 2. Read the ID field
    if(!RxMsg->Ide)
    {
        RxMsg->Id = (can2_rxBuffer[1] >> 18) & 0x7FF;      // std id
    }
    else
    {
        RxMsg->Id = (can2_rxBuffer[1] & 0x1FFFFFFF);       // Ext id
    }        
    
    // 3. Read the data field.
    if(!RxMsg->Rtr)
    {                      
        RxMsg->Data[0] = (can2_rxBuffer[2] >> 24) & 0xFF;
        RxMsg->Data[1] = (can2_rxBuffer[2] >> 16) & 0xFF;
        RxMsg->Data[2] = (can2_rxBuffer[2] >> 8) & 0xFF;
        RxMsg->Data[3] = (can2_rxBuffer[2]) & 0xFF;
        RxMsg->Data[4] = (can2_rxBuffer[3] >> 24) & 0xFF;
        RxMsg->Data[5] = (can2_rxBuffer[3] >> 16) & 0xFF;
        RxMsg->Data[6] = (can2_rxBuffer[3] >> 8) & 0xFF;
        RxMsg->Data[7] = (can2_rxBuffer[3]) & 0xFF;
    }
    else               //  Ext id  no data
    {
        for(int i=0; i<8; i++)
        {
            RxMsg->Data[i] = 0;
        }
    }
}

void FLEXCAN0_Filter(void)
{
    CAN0->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 0] = (0x55 &0x7FF) << 19; // ID filter table element 0
    CAN0->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 1] = ((0x0F000F56&0x1FFFFFFF) << 1) | 0x40000000; // element 1 IDE=1 EXT id
    CAN0->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 2] = (0x57 &0x7FF) << 19; // element 2
    CAN0->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 3] = (0x58 &0x7FF) << 19; // element 3

    CAN0->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 4] = ((0x59 &0x7FF) << 19) | 0x80000000; // element 4 RTR=1
    CAN0->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 5] = (0x5A &0x7FF) << 19; // element 5
    CAN0->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 6] = (0x5B &0x7FF) << 19; // element 6
    CAN0->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 7] = (0x5C &0x7FF) << 19; // element 7
    
    CAN0->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 8] = (0x60 &0x7FF) << 19; // element 8
    CAN0->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 9] = (0x61 &0x7FF) << 19; // element 9
    CAN0->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 10] = (0x62 &0x7FF) << 19; // element 10
    CAN0->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 11] = (0x63 &0x7FF) << 19; // element 11
}

void FLEXCAN1_Filter(void)
{
    CAN1->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 0] = (0x55 &0x7FF) << 19; // ID filter table element 0
    CAN1->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 1] = ((0x0F000F56&0x1FFFFFFF) << 1) | 0x40000000; // element 1 IDE=1 EXT id
    CAN1->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 2] = (0x57 &0x7FF) << 19; // element 2
    CAN1->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 3] = (0x58 &0x7FF) << 19; // element 3

    CAN1->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 4] = ((0x59 &0x7FF) << 19) | 0x80000000; // element 4 RTR=1
    CAN1->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 5] = (0x5A &0x7FF) << 19; // element 5
    CAN1->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 6] = (0x5B &0x7FF) << 19; // element 6
    CAN1->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 7] = (0x5C &0x7FF) << 19; // element 7
    
    CAN1->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 8] = (0x60 &0x7FF) << 19; // element 8
    CAN1->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 9] = (0x61 &0x7FF) << 19; // element 9
    CAN1->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 10] = (0x62 &0x7FF) << 19; // element 10
    CAN1->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 11] = (0x63 &0x7FF) << 19; // element 11
}

void FLEXCAN2_Filter(void)
{
    CAN2->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 0] = (0x55 &0x7FF) << 19; // ID filter table element 0
    CAN2->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 1] = ((0x0F000F56&0x1FFFFFFF) << 1) | 0x40000000; // element 1 IDE=1 EXT id
    CAN2->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 2] = (0x57 &0x7FF) << 19; // element 2
    CAN2->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 3] = (0x58 &0x7FF) << 19; // element 3

    CAN2->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 4] = ((0x59 &0x7FF) << 19) | 0x80000000; // element 4 RTR=1
    CAN2->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 5] = (0x5A &0x7FF) << 19; // element 5
    CAN2->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 6] = (0x5B &0x7FF) << 19; // element 6
    CAN2->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 7] = (0x5C &0x7FF) << 19; // element 7
    
    CAN2->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 8] = (0x60 &0x7FF) << 19; // element 8
    CAN2->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 9] = (0x61 &0x7FF) << 19; // element 9
    CAN2->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 10] = (0x62 &0x7FF) << 19; // element 10
    CAN2->RAMn[MB_FIFO_NUM*MSG_BUF_SIZE + 11] = (0x63 &0x7FF) << 19; // element 11
}


void FLEXCAN_init(uint8_t CANChannel)
{   
    uint32_t i = 0;
    CAN_Type *CANBaseAdd;
    const CAN_Cfg *cfg=&cancfg[CANChannel];
    const CAN_Dma_Cfg *dma= &cfg->dmaCfg;
    
    if(CANChannel == 0)
    {
        FLEXCAN0_Port_Init();
        CANBaseAdd=CAN0;
        PCC->PCCn[PCC_FlexCAN0_INDEX] |= PCC_PCCn_CGC_MASK; /* CGC=1: enable clock to FlexCAN0 */
    }
    else if(CANChannel == 1)
    {
        FLEXCAN1_Port_Init();
        CANBaseAdd=CAN1;
        PCC->PCCn[PCC_FlexCAN1_INDEX] |= PCC_PCCn_CGC_MASK; /* CGC=1: enable clock to FlexCAN0 */
    }
    else if(CANChannel == 2)
    {
        FLEXCAN2_Port_Init();
        CANBaseAdd=CAN2;
        PCC->PCCn[PCC_FlexCAN2_INDEX] |= PCC_PCCn_CGC_MASK; /* CGC=1: enable clock to FlexCAN0 */
    }
    

    CANBaseAdd->MCR |= CAN_MCR_SOFTRST_MASK;      //Soft Reset
    CANBaseAdd->MCR &= ~CAN_MCR_SOFTRST_MASK;
    
    CANBaseAdd->MCR |= CAN_MCR_MDIS_MASK;         /* MDIS=1: Disable module before selecting clock */
    CANBaseAdd->CTRL1 &= ~CAN_CTRL1_CLKSRC_MASK;  /* CLKSRC=0: Clock Source = oscillator (8 MHz) */
    CANBaseAdd->MCR &= ~CAN_MCR_MDIS_MASK;        /* MDIS=0; Enable the FlexCAN module. (Sets FRZ, HALT)	*/  
    // After the clock source is selected and the module is enabled (MCR[MDIS] bit negated), FlexCAN automatically enters Freeze mode. In Freeze mode
    // CANBaseAdd->MCR |= CAN_MCR_FRZ_MASK;          /*(Sets FRZ, HALT)	*/ 
    while (!((CANBaseAdd->MCR & CAN_MCR_FRZACK_MASK) >> CAN_MCR_FRZACK_SHIFT)) {}
      
    // Step1: Initialize MCR
    CANBaseAdd->MCR |= CAN_MCR_IRMQ_MASK // a: IRMQ=1, enable the individual filtering per MB and reception queue features            
              | CAN_MCR_WRNEN_MASK // b: WRNEN=1, enable the warning interrupts
#if LOOPBACK == 0
              | CAN_MCR_SRXDIS_MASK // c: SRXDIS=1, disable frame self reception
#endif
              | CAN_MCR_RFEN_MASK // d: RFEN=1, Enable the Rx FIFO, MBs 0 to 5 cannot be used for normal reception and transmission(they have been uesed for the FIFO engine)
#if DMA_ENABLE == 1
              |CAN_MCR_DMA_MASK   /* DMA enabled */
#endif
              // f: PNET_EN=0, dont use pretended networking
              | CAN_MCR_AEN_MASK// g: AEN=1, use Tx Abort mechanism
              | CAN_MCR_LPRIOEN_MASK   // h: PRIOEN=1, Local Priority enabled          
              | CAN_MCR_IDAM(0)// IDAM=0, ID Acceptance Mode=Format A: One full ID (standard and extended) per ID filter table element.
              | CAN_MCR_MAXMB(cfg->NumOfMbs); // MAXMB = Rx FIFO + ID filter table space(CTRL2[REFN]), default=16             
    
    // Step2: Initialize CTRL1 or CBT
    // The CAN bit variables in CTRL1 and in CBT are stored in the same register.
    // Configure for CAN bit rate = 500 Kbps, 16 time quanta for 1 bit
    CANBaseAdd->CTRL1 |= CAN_CTRL1_PRESDIV(0)  // Tq = fcanclk / prediv = 8MHz / 1 = 8MHz
                | CAN_CTRL1_RJW(3)  // RJW: since Phase_Seg2 >=4, RJW+1=4 so RJW=3.
                | CAN_CTRL1_PSEG1(3)  // Phase Segment 1 = PSEG1 + 1
                | CAN_CTRL1_PSEG2(3)  // Phase Segment 2 = PSEG2 + 1
#if LOOPBACK == 1
                |CAN_CTRL1_LPB_MASK  /* LOOPBACK enabled */
#endif                
                | CAN_CTRL1_PROPSEG(6)  // Propagation Segment = PROPSEG + 1
                | CAN_CTRL1_SMP(1)    
                | CAN_CTRL1_LBUF(1);   // LBUF=1, Lowest number buffer is transmitted first.(MCR[LPRIOEN] + LBUF <= transmit priority)
                                   
    // Step3: Initialize the message buffers    
    // MB & Rx Individual Mask registers are not affected by reset, so they are not initialized automatically.
    // payload=8, MB0~5 used for FIFO engine(contains message received but not read)
    // CAN0: clear 32 message buffer x 4 words/msg, buf = 128 words
    // CAN0 contains 32MBs         
    for(i=24; i<cfg->NumOfWords; i++)   //i = Number of Rx FIFO filter elements; Table 53-6. Rx FIFO filter: possible structures
    {   					 /* CAN0: clear 32 msg bufs x 4 words/msg buf = 128 words */
        CANBaseAdd->RAMn[i] = 0;   /* Clear msg buf word */
    }
    // set the ID Table, assuming CTRL2[RFFN=2]     //2. Write the ID word   
    if(CANChannel == 0)
    {
        FLEXCAN0_Filter();
    }
    else if(CANChannel == 1)
    {
        FLEXCAN1_Filter();
    }
    else if(CANChannel == 2)
    {
        FLEXCAN2_Filter();
    }

    // Step4: Initialize RXIMRn(Rx Individual Mask registers)
    // In FRZ mode, init CAN0 16 individual msg buf filters . there are total 32MBs for CAN0
    for(i=0; i<cfg->NumOfMbs; i++ )           /* the mailbox filter and Rx FIFO ID filter table element in distinct ways.*/
    {          					
        CANBaseAdd->RXIMR[i] = 0xFFFFFFFF;  	/* 1b - The corresponding bit in the filter is checked. 0b-The corresponding bit in the filter is "don't care." */
    }
    CANBaseAdd->RXMGMASK = 0x1FFFFFFF;  				/* Mailboxes Global Mask. Global acceptance mask: check all ID bits 	*/
                                                /* 1b - The corresponding bit in the filter is checked. 0b-The corresponding bit in the filter is "don't care." */
    CANBaseAdd->RX14MASK = 0x1FFFFFFF;
    CANBaseAdd->RX15MASK = 0x1FFFFFFF;    
    CANBaseAdd->RXFGMASK = 0x1FFFFFFF;               //FIFO Global Mask

    // Step5: Set required interrupt mask bits in  IMASK registers CTRL1 / CTRL2 registers
    // enable interrupt
#if DMA_ENABLE == 0
    CANBaseAdd->CTRL1 |= CAN_CTRL1_RWRNMSK_MASK; // enable Rx warning interrupt
    CANBaseAdd->IMASK1 |= CAN_IMASK1_BUF31TO0M(1 << MB_FIFO_IDX_RX); /* Buffer MB i Mask: Open FIFO receives interrupt */
    // CAN0->IMASK1 |= CAN_IMASK1_BUF31TO0M(1 << MB_FIFO_IDX_TX); /* MBx interrupt mask*/
    CANBaseAdd->IMASK1 |= CAN_IMASK1_BUF31TO0M(1 << 5);    
#endif
    CANBaseAdd->CTRL2 |= 0x2000000;        //Number of Rx FIFO filter elements   RFFN = n*8+8  
    // Step6: If Pretended Networking mode is enabled, configure the necessary registers for selective wakeup.

    // Step7: nagate HALT
    CANBaseAdd->MCR &= 0xBFFFFFFF;             //disable Freeze mode.
    CANBaseAdd->MCR &= ~CAN_MCR_HALT_MASK;       /* Negate HALT bit */ 
                 
    while ((CANBaseAdd->MCR & CAN_MCR_FRZACK_MASK) >> CAN_MCR_FRZACK_SHIFT) {}
    /* Good practice: wait for FRZACK to clear (not in freeze mode) */
    while ((CANBaseAdd->MCR & CAN_MCR_NOTRDY_MASK) >> CAN_MCR_NOTRDY_SHIFT) {}
    /* Good practice: wait for NOTRDY to clear (module ready) */
#if DMA_ENABLE == 0
        FLEXCAN0_NVIC_init_IRQs();
#else
        CAN_DMA_init(dma);
        FLEXCAN_DMAMUX_Init(dma);
        FLEXCAN_DMA_NVIC_init_IRQs(dma);
#endif
}



/*************************************************************/
/*****                   CAN2.0发送函数                  *****/
/*****Coder:   djf                                       *****/
/*****Id:      报文Id                                        */
/*****Ide:     0 标准帧、1 扩展帧                            */
/*****Rtr:     0 数据帧、1 远程帧                            */
/*****Length:  报文数据长度(<=8)                             */
/*****Prty:    报文发送优先级 0最高                          */ 
/***** *CAN_Frame:    发送结构体指针                         */    
/*************************************************************/
bool FLEXCAN_TX_Frame(uint8_t CANChannel,CAN_FrameStruct *CAN_Frame)
{ 
    uint8_t code = 0;
    CAN_Type *CANBaseAdd;
    
    if(CANChannel == 0)
    {
        CANBaseAdd=CAN0;
    }
    else if(CANChannel == 1)
    {
        CANBaseAdd=CAN1;
    }
    else if(CANChannel == 2)
    {
        CANBaseAdd=CAN2;
    }
    
    //4. Read back the CODE field to check if the transmission was aborted or transmitted
    code = (CANBaseAdd->RAMn[FIFO_IDX_TXMB*MSG_BUF_SIZE + 0]&CAN_WMBn_CS_CODE_MASK) >> CAN_WMBn_CS_CODE_SHIFT;
    if(0x80==code)           //MB is not active
    {
        if(CANChannel == 0)
        {
            txBusy++;
        }
        else if(CANChannel == 1)
        {
            can1_txBusy++;
        }
        else if(CANChannel == 2)
        {
            can2_txBusy++;
        }
        return (false);
    }
    else
    {
    
    }
    //5. Clear the corresponding interrupt flag.
    CANBaseAdd->IFLAG1 |= (1 << FIFO_IDX_TXMB); // Clear CAN0 13 flag without clearing other.
    
    //6. Write the ID register
    /*MB word1*/
    if(!CAN_Frame->Ide)     // Standard frame
    {
        CANBaseAdd->RAMn[FIFO_IDX_TXMB*MSG_BUF_SIZE + 1] = (CAN_Frame->Prty << 29)|((CAN_Frame->Id&0x7FF) << 18u);  // std id
    }
    else        // Extended frame
    {
        CANBaseAdd->RAMn[FIFO_IDX_TXMB*MSG_BUF_SIZE + 1] = (CAN_Frame->Prty << 29)|(CAN_Frame->Id&0x1FFFFFFF);  // Ext id
    }   
    
    //7. Write payload Data bytes.
    if(!CAN_Frame->Rtr)                    // Data frame 
    {
        /*MB word2*/
        CANBaseAdd->RAMn[FIFO_IDX_TXMB*MSG_BUF_SIZE + 2] = CAN_RAMn_DATA_BYTE_0(CAN_Frame->Data[0])                
                                                   | CAN_RAMn_DATA_BYTE_1(CAN_Frame->Data[1])
                                                   | CAN_RAMn_DATA_BYTE_2(CAN_Frame->Data[2])
                                                   | CAN_RAMn_DATA_BYTE_3(CAN_Frame->Data[3]);
        /*MB word3*/
        CANBaseAdd->RAMn[FIFO_IDX_TXMB*MSG_BUF_SIZE + 3] = CAN_RAMn_DATA_BYTE_0(CAN_Frame->Data[4])                
                                                   | CAN_RAMn_DATA_BYTE_1(CAN_Frame->Data[5])
                                                   | CAN_RAMn_DATA_BYTE_2(CAN_Frame->Data[6])
                                                   | CAN_RAMn_DATA_BYTE_3(CAN_Frame->Data[7]);
    }
    else                        // Remote frame
    {
    
    }
   
    //8. Configure the Control and Status word with the desired configuration    
    /*MB word1*/
    CANBaseAdd->RAMn[FIFO_IDX_TXMB*MSG_BUF_SIZE + 0] &= 0x1FFFFFFF;         //EDL=0; BRS=0; ESI=0; CANFD not used 
    CANBaseAdd->RAMn[FIFO_IDX_TXMB*MSG_BUF_SIZE + 0] = CAN_WMBn_CS_IDE(CAN_Frame->Ide)
                                               | CAN_WMBn_CS_RTR(CAN_Frame->Rtr)            
                                               | CAN_WMBn_CS_SRR(CAN_Frame->Srr)            
                                               | CAN_WMBn_CS_DLC(CAN_Frame->Len)
                                               | CAN_WMBn_CS_CODE(0x0C);

    if(CANChannel == 0)
    {
        txCounter++;
    }
    else if(CANChannel == 1)
    {
        can1_txCounter++;
    }
    else if(CANChannel == 2)
    {
        can2_txCounter++;
    }

    return (true);
}



/*************************************************************/
/*****                   CAN2.0接收函数                  *****/
/*****Coder:   djf                                       *****/
/*****Id:      报文Id                                        */
/*****Ide:     0 标准帧、1 扩展帧                            */
/*****Rtr:     0 数据帧、1 远程帧                            */
/*****Length:  报文数据长度(<=8)                             */
/*****Prty:    报文发送优先级 0最高                          */ 
/**** *RxMsg:   接收结构体指针                               */    
/*************************************************************/
void FLEXCAN_RX_Frame(uint8_t CANChannel,CAN_FrameStruct *RxMsg)
{
    uint8_t i = 0;
    CAN_Type *CANBaseAdd;
    
    if(CANChannel == 0)
    {
        CANBaseAdd=CAN0;
    }
    else if(CANChannel == 1)
    {
        CANBaseAdd=CAN1;
    }
    else if(CANChannel == 2)
    {
        CANBaseAdd=CAN2;
    }
    
    // when received CAN message by FIFO (MB0~5), interrupt flag set by IFLAG5(not IFLAG0~4)
    if(CAN0->IFLAG1 & 0x20)
    {
        // 1. Read the Control and Status word
        RxMsg->Ide = (CANBaseAdd->RAMn[FIFO_IDX_RXMB*MSG_BUF_SIZE+0] & CAN_WMBn_CS_IDE_MASK) >> CAN_WMBn_CS_IDE_SHIFT;
        RxMsg->Rtr = (CANBaseAdd->RAMn[FIFO_IDX_RXMB*MSG_BUF_SIZE+0] & CAN_WMBn_CS_RTR_MASK) >> CAN_WMBn_CS_RTR_SHIFT;
        RxMsg->Len = (CANBaseAdd->RAMn[FIFO_IDX_RXMB*MSG_BUF_SIZE+0] & CAN_WMBn_CS_DLC_MASK) >> CAN_WMBn_CS_DLC_SHIFT;
        RxMsg->Srr = (CANBaseAdd->RAMn[FIFO_IDX_RXMB*MSG_BUF_SIZE+0] & CAN_WMBn_CS_SRR_MASK) >> CAN_WMBn_CS_SRR_SHIFT;
        RxMsg->timestamp = (CANBaseAdd->RAMn[FIFO_IDX_RXMB*MSG_BUF_SIZE+0] & 0x000FFFF);
        
        // 2. Read the ID field
        if(!RxMsg->Ide)
        {
            RxMsg->Id = (CANBaseAdd->RAMn[FIFO_IDX_RXMB*MSG_BUF_SIZE+1] >> 18) & 0x7FF;      // std id
        }
        else
        {
            RxMsg->Id = (CANBaseAdd->RAMn[FIFO_IDX_RXMB*MSG_BUF_SIZE+1] & 0x1FFFFFFF);       // Ext id
        }        
        
        // 3. Read the data field.
        if(!RxMsg->Rtr)
        {                      
            RxMsg->Data[0] = (CANBaseAdd->RAMn[FIFO_IDX_RXMB*MSG_BUF_SIZE+2] >> 24) & 0xFF;
            RxMsg->Data[1] = (CANBaseAdd->RAMn[FIFO_IDX_RXMB*MSG_BUF_SIZE+2] >> 16) & 0xFF;
            RxMsg->Data[2] = (CANBaseAdd->RAMn[FIFO_IDX_RXMB*MSG_BUF_SIZE+2] >> 8) & 0xFF;
            RxMsg->Data[3] = (CANBaseAdd->RAMn[FIFO_IDX_RXMB*MSG_BUF_SIZE+2]) & 0xFF;
            RxMsg->Data[4] = (CANBaseAdd->RAMn[FIFO_IDX_RXMB*MSG_BUF_SIZE+3] >> 24) & 0xFF;
            RxMsg->Data[5] = (CANBaseAdd->RAMn[FIFO_IDX_RXMB*MSG_BUF_SIZE+3] >> 16) & 0xFF;
            RxMsg->Data[6] = (CANBaseAdd->RAMn[FIFO_IDX_RXMB*MSG_BUF_SIZE+3] >> 8) & 0xFF;
            RxMsg->Data[7] = (CANBaseAdd->RAMn[FIFO_IDX_RXMB*MSG_BUF_SIZE+3]) & 0xFF;
        }
        else               //  Ext id  no data
        {
            for(i=0; i<8; i++)
            {
                RxMsg->Data[i] = 0;
            }
        }
        
        // 4. Read the RXFIR register
        (void)CANBaseAdd->RXFIR;
       
        // 5. Clear the Frames Available in Rx FIFO interrupt by writing one to IFLAG1             
        CANBaseAdd->IFLAG1 |= 0x20;       /* Clear CAN0 MB5 flag*/
        
    }
    else
    {
    
    }
    
   // rxCounter++;
    
}


/*
 * ===================================================
 * Function :  FLEXCAN0_init For Classical CAN2.0 
 * 1. CAN configuration, set baud rate = 500Kbps 
 * 2. @note CAN Baud rate calculation
 *    Tq = (PRESDIV + 1) / f_canclk = 1 / 8M 
 *    1 CAN Bit Time = (1 + (PROPSEG + PSEG1 + 2) + (PSEG2 + 1)) * Tq
 *    = (1 + (6 + 3 + 2) + (3 + 1) * 1/8M
 *    = 16 * 1/8M = 2us 
 *    Baud Rate = 1/2us = 500Kbps 
 * 3. configure 1MB = 8 CAN->RAMn = 32byte
 * 4. MB6 ~ FIFO Rx
 * 5. FIFO receives interrupt 
 * 6. disable frame self reception
 * 7. RFFN = 2,ID filter table = 2*8+8 = 24  
 * 8. ID Acceptance Mode = Format A: 
 * Coder :  djf
 * Date/Time :  2020/07/01 
 * ===================================================
 */
void FLEXCAN0_init(void)                   //Classical
{   
    FLEXCAN_init(0);
}

void FLEXCAN0_NVIC_init_IRQs (void)
{
    S32_NVIC->ICPR[1] = 1 << (CAN0_ORed_0_15_MB_IRQn % 32);  /* IRQ81-CHA0 0-15: clr any pending IRQ*/
    S32_NVIC->ISER[(uint32_t)(CAN0_ORed_0_15_MB_IRQn) >> 5U] = (uint32_t)(1UL << ((uint32_t)(CAN0_ORed_0_15_MB_IRQn) & (uint32_t)0x1FU));
    S32_NVIC->IP[81] = 0xb;              /* IRQ81-CAN0 0-15: priority 10 of 0-15*/
}

bool FLEXCAN0_TX_Frame(CAN_FrameStruct *CAN_Frame)
{ 
    return FLEXCAN_TX_Frame(0,CAN_Frame);
}


/*********************************************************************
 * 函数原型：void CAN0_ORed_0_15_MB_IRQHandler(void)
 * 功        能：CAN0中断服务器
 * 输入参数：无
 * 返回参数：无
 *
 * 其他说明：
*********************************************************************/

void CAN0_ORed_0_15_MB_IRQHandler(void)
{
    rxCounter++;
    //FLEXCAN0_RX_Frame(&canRxMsg);
    FLEXCAN_RX_Frame(0,&canRxMsg);

    // Rx warning interrupt - MB0~5 full(unread message increase to 5 from 4)
    if(CAN0->IFLAG1 & (1 << MB_FIFO_IDX_RX))
    {
        CAN0->IFLAG1 |= 1 << MB_FIFO_IDX_RX;       /* Clear CAN0 MB6 flag */
    }      
    
    // Rx overflow - MB0~5 full
    if(CAN0->IFLAG1 & 0x80)
    {
        CAN0->IFLAG1 |= 0x80;       /* Clear CAN0 MB6 flag*/
    }
    
}

uint32_t aa = 0;

void FLEXCAN0_TX_Msg(void)
{
    //CAN_FrameStruct SendMsg = {0};
    
    if(255>aa)
    {
        aa++;
    }
    else
    {
        aa = 0;
    } 
        
    canTxMsg.Data[1] = aa;
    canTxMsg.Data[2] = 255 - aa;
    canTxMsg.Id = 0x55;
    canTxMsg.Ide = 0;
    canTxMsg.Rtr = 0;
    canTxMsg.Len = 8;
    canTxMsg.Prty = 0;
    canTxMsg.Srr = 1;
    
    (void)FLEXCAN0_TX_Frame(&canTxMsg);

}

void FLEXCAN1_init(void)
{   
    FLEXCAN_init(1);
}

void FLEXCAN1_NVIC_init_IRQs (void)
{
    S32_NVIC->ICPR[1] = 1 << (CAN1_ORed_0_15_MB_IRQn % 32);  /* IRQ88-CHA0 0-15: clr any pending IRQ*/
    S32_NVIC->ISER[(uint32_t)(CAN1_ORed_0_15_MB_IRQn) >> 5U] = (uint32_t)(1UL << ((uint32_t)(CAN1_ORed_0_15_MB_IRQn) & (uint32_t)0x1FU));
    S32_NVIC->IP[88] = 0xb;              /* IRQ81-CAN0 0-15: priority 10 of 0-15*/
}

/*************************************************************/
/*****                   CAN2.0发送函数                  *****/
/*****Coder:   djf                                       *****/
/*****Id:      报文Id                                        */
/*****Ide:     0 标准帧、1 扩展帧                            */
/*****Rtr:     0 数据帧、1 远程帧                            */
/*****Length:  报文数据长度(<=8)                             */
/*****Prty:    报文发送优先级 0最高                          */ 
/***** *CAN_Frame:    发送结构体指针                         */    
/*************************************************************/

bool FLEXCAN1_TX_Frame(CAN_FrameStruct *CAN_Frame)
{ 
    return FLEXCAN_TX_Frame(1,CAN_Frame);
}


/*********************************************************************
 * 函数原型：void CAN0_ORed_0_15_MB_IRQHandler(void)
 * 功        能：CAN0中断服务器
 * 输入参数：无
 * 返回参数：无
 *
 * 其他说明：
*********************************************************************/

void CAN1_ORed_0_15_MB_IRQHandler(void)
{
    can1_rxCounter++;
    //FLEXCAN1_RX_Frame(&can1RxMsg);
    FLEXCAN_RX_Frame(1,&canRxMsg);

    // Rx warning interrupt - MB0~5 full(unread message increase to 5 from 4)
    if(CAN1->IFLAG1 & (1 << MB_FIFO_IDX_RX))
    {
        CAN1->IFLAG1 |= 1 << MB_FIFO_IDX_RX;       /* Clear CAN0 MB6 flag */
    }
    
    // Rx overflow - MB0~5 full
    if(CAN1->IFLAG1 & 0x80)
    {
        CAN1->IFLAG1 |= 0x80;       /* Clear CAN0 MB6 flag*/
    }
    
}

uint32_t bb = 0;

void FLEXCAN1_TX_Msg(void)
{
    //CAN_FrameStruct SendMsg = {0};
    
    if(255>bb)
    {
        bb++;
    }
    else
    {
        bb = 0;
    } 
        
    can1TxMsg.Data[1] = aa;
    can1TxMsg.Data[2] = 255 - aa;
    can1TxMsg.Id = 0x55;
    can1TxMsg.Ide = 0;
    can1TxMsg.Rtr = 0;
    can1TxMsg.Len = 8;
    can1TxMsg.Prty = 0;
    can1TxMsg.Srr = 1;
    
    (void)FLEXCAN1_TX_Frame(&can1TxMsg);

}

//CAN2
void FLEXCAN2_init(void)
{   
    FLEXCAN_init(2);
}

void FLEXCAN2_NVIC_init_IRQs (void)
{
    S32_NVIC->ICPR[(uint32_t)(CAN2_ORed_0_15_MB_IRQn) >> 5U] = (uint32_t)(1UL << ((uint32_t)(CAN2_ORed_0_15_MB_IRQn) & (uint32_t)0x1FU));
    //S32_NVIC->ICPR[1] = (uint32_t)(1 << (uint32_t)(CAN2_ORed_0_15_MB_IRQn % 32));  /* IRQ95-CHA0 0-15: clr any pending IRQ*/
    S32_NVIC->ISER[(uint32_t)(CAN2_ORed_0_15_MB_IRQn) >> 5U] = (uint32_t)(1UL << ((uint32_t)(CAN2_ORed_0_15_MB_IRQn) & (uint32_t)0x1FU));
    S32_NVIC->IP[95] = 0xb;              /* IRQ95-CAN0 0-15: priority 10 of 0-15*/
}

/*************************************************************/
/*****                   CAN2.0发送函数                  *****/
/*****Coder:   djf                                       *****/
/*****Id:      报文Id                                        */
/*****Ide:     0 标准帧、1 扩展帧                            */
/*****Rtr:     0 数据帧、1 远程帧                            */
/*****Length:  报文数据长度(<=8)                             */
/*****Prty:    报文发送优先级 0最高                          */ 
/***** *CAN_Frame:    发送结构体指针                         */    
/*************************************************************/

bool FLEXCAN2_TX_Frame(CAN_FrameStruct *CAN_Frame)
{ 
    return FLEXCAN_TX_Frame(2,CAN_Frame);
}


/*********************************************************************
 * 函数原型：void CAN0_ORed_0_15_MB_IRQHandler(void)
 * 功        能：CAN0中断服务器
 * 输入参数：无
 * 返回参数：无
 *
 * 其他说明：
*********************************************************************/

void CAN2_ORed_0_15_MB_IRQHandler(void)
{
    can2_rxCounter++;
    //FLEXCAN2_RX_Frame(&can2RxMsg);
    FLEXCAN_RX_Frame(2,&canRxMsg);

    // Rx warning interrupt - MB0~5 full(unread message increase to 5 from 4)
    if(CAN2->IFLAG1 & (1 << MB_FIFO_IDX_RX))
    {
        CAN2->IFLAG1 |= 1 << MB_FIFO_IDX_RX;       /* Clear CAN0 MB6 flag */
    }
    
    // Rx overflow - MB0~5 full
    if(CAN2->IFLAG1 & 0x80)
    {
        CAN2->IFLAG1 |= 0x80;       /* Clear CAN0 MB6 flag*/
    }
    
}

uint32_t cc = 0;

void FLEXCAN2_TX_Msg(void)
{
    //CAN_FrameStruct SendMsg = {0};
    
    if(255>bb)
    {
        cc++;
    }
    else
    {
        cc = 0;
    } 
        
    can2TxMsg.Data[1] = aa;
    can2TxMsg.Data[2] = 255 - aa;
    can2TxMsg.Id = 0x55;
    can2TxMsg.Ide = 0;
    can2TxMsg.Rtr = 0;
    can2TxMsg.Len = 8;
    can2TxMsg.Prty = 0;
    can2TxMsg.Srr = 1;
    
    (void)FLEXCAN2_TX_Frame(&can2TxMsg);

}


